import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/Addons.js';
import { GLTFLoader } from 'three/examples/jsm/Addons.js';
import { GLTFExporter } from 'three/examples/jsm/Addons.js';

// 模块内全局变量
let scene, renderer, camera, controls;
let bodyModel, glassesModel, faceModel;
let oldmap;
let gltfModelList = [], addGltfModel = [];
let loader;
let isModelSelected = false;
let currentGlbList = [];
let containerRef; // 保存容器引用，用于自适应尺寸


/**
 * 初始化3D场景（支持全向旋转，自动适配容器）
 * @param {HTMLElement} container - 承载3D渲染的容器DOM（必须传入）
 * @param {string} baseGlbUrl - 基础模型的GLB文件URL
 * @param {Array} glbList - 附加模型配置列表
 * @param {THREE.Texture} texture - 基础模型的纹理替换
 * @returns {Promise<void>} - 初始化完成Promise
 */
function init(container, baseGlbUrl, glbList = [], texture) {
  // 必传参数校验
  if (!container) {
    console.error("初始化失败：必须传入有效的容器DOM");
    return Promise.reject(new Error("无效的容器DOM"));
  }
  if (!baseGlbUrl) {
    console.error("初始化失败：必须传入基础模型URL");
    return Promise.reject(new Error("无效的基础模型URL"));
  }
  if(container.children.length > 0) {
    container.removeChild(container.children[0])
  }
  console.log(baseGlbUrl)
  // 保存容器引用
  containerRef = container;
  currentGlbList = glbList;

  // 1. 初始化核心对象
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffffff);
  loader = new GLTFLoader();

  // 2. 灯光配置（增强照明，避免模型过暗）
  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.5);
  hemiLight.position.set(0, 20, 0);
  scene.add(hemiLight);

  const dirLight = new THREE.DirectionalLight(0xffffff, 1.5);
  dirLight.position.set(5, 20, 10);
  dirLight.castShadow = true;
  dirLight.shadow.camera.top = 40;
  dirLight.shadow.camera.bottom = -40;
  dirLight.shadow.camera.left = -40;
  dirLight.shadow.camera.right = 40;
  dirLight.shadow.camera.near = 0.1;
  dirLight.shadow.camera.far = 100;
  scene.add(dirLight);

  // 3. 地面网格（可选，可移除）
  const groundMesh = new THREE.Mesh(
    new THREE.PlaneGeometry(100, 100),
    new THREE.MeshPhongMaterial({ color: 0xf0f0f0, depthWrite: false })
  );
  groundMesh.rotation.x = -Math.PI / 2;
  groundMesh.receiveShadow = true;
  scene.add(groundMesh);

  // 4. 渲染器配置（自适应容器尺寸）
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    preserveDrawingBuffer: true,
    physicalCorrectLights: true,
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(container.offsetWidth, container.offsetHeight);
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.shadowMap.enabled = true;
  container.appendChild(renderer.domElement);

  // 5. 相机配置（初始参数，加载模型后会自动调整）
  camera = new THREE.PerspectiveCamera(
    60, // 更宽的视野，避免模型被截断
    container.offsetWidth / container.offsetHeight,
    0.1,
    1000
  );
  camera.position.set(0, 5, 10); // 初始位置，会自动调整

  // 6. 轨道控制器（支持全向操作）
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enablePan = true; // 允许平移
  controls.enableZoom = true; // 允许缩放
  controls.enableRotate = true; // 允许全向旋转
  controls.minPolarAngle = 0; // 取消极角限制（允许上下旋转）
  controls.maxPolarAngle = Math.PI; 
  controls.minDistance = 1; // 缩小限制
  controls.maxDistance = 50; // 放大限制
  controls.target = new THREE.Vector3(0, 2, 0); // 初始目标点
  controls.enableDamping = true; // 平滑动画
  controls.dampingFactor = 0.1;
  controls.update();

  // 7. 加载基础模型并自动适配显示
  return new Promise((resolve, reject) => {
    loader.load(
      baseGlbUrl,
      (gltf) => {
        bodyModel = gltf.scene;
        bodyModel.traverse((obj) => {
          if (obj.isMesh) {
            oldmap = obj.material.map;
            if (texture) obj.material.map = texture;
            obj.castShadow = true;
            obj.receiveShadow = true; // 接收阴影，增强立体感
          }
        });

        // 关键：自动调整相机位置以完整显示模型
        fitModelToContainer(bodyModel);

        gltfModelList.push(bodyModel);
        scene.add(bodyModel);
        animate();
        resolve();
      },
      undefined,
      (error) => {
        console.error(`基础模型加载失败：${baseGlbUrl}`, error);
        reject(error);
      }
    );
  });
}

/**
 * 自动调整相机位置，确保模型完整显示在容器中
 * @param {THREE.Object3D} model - 要显示的模型
 */
function fitModelToContainer(model) {
  if (!model || !camera || !controls) return;

  // 计算模型边界框
  const box = new THREE.Box3().setFromObject(model);
  const size = box.getSize(new THREE.Vector3());
  const center = box.getCenter(new THREE.Vector3());

  // 计算模型最大尺寸（用于确定相机距离）
  const maxDim = Math.max(size.x, size.y, size.z);
  const fov = camera.fov * (Math.PI / 180);
  let cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2));

  // 调整相机位置（后退一定距离，确保完整显示）
  cameraZ *= 1.5; // 增加1.5倍缓冲
  camera.position.z = cameraZ;
  
  // 调整目标点到模型中心
  controls.target.copy(center);
  camera.lookAt(center);
  
  // 更新控制器
  controls.update();
}

/**
 * 响应式适配容器尺寸变化
 */
function handleResize() {
  if (!containerRef || !camera || !renderer) return;

  // 更新相机比例
  camera.aspect = containerRef.offsetWidth / containerRef.offsetHeight;
  camera.updateProjectionMatrix();

  // 更新渲染器尺寸
  renderer.setSize(containerRef.offsetWidth, containerRef.offsetHeight);
}

/**
 * 渲染循环（带阻尼动画）
 */
function animate() {
  requestAnimationFrame(animate);
  if (controls) controls.update(); // 支持阻尼效果
  if (renderer && scene && camera) {
    renderer.render(scene, camera);
  }
}

// ------------------------------
// 下载模型功能
// ------------------------------
function downloadModel(fileDownUrl, filename = 'model.glb') {
  // 1. 加强参数校验：确保下载底子有效（非空且为合法字符串）
  if (!fileDownUrl || typeof fileDownUrl !== 'string') {
    const errMsg = fileDownUrl === null ? '请先上传模型（未获取到下载资源）' : '下载地址无效（需传入合法的 URL 字符串）';
    alert(errMsg);
    const err = new Error(errMsg);
    console.error(err);
    return Promise.reject(err);
  }

  // 2. 校验文件名（避免非法字符，确保后缀合理）
  const validFilename = filename.trim() || 'model.glb';
  // 若文件名无后缀，默认补充 glb（可根据实际资源类型调整，如 .obj、.fbx 等）
  const hasFileExt = validFilename.includes('.');
  const finalFilename = hasFileExt ? validFilename : `${validFilename}.glb`;

  return new Promise((resolve, reject) => {
    try {
      // 3. 创建下载链接元素，触发下载
      const downloadLink = document.createElement('a');
      // 设置下载地址（支持普通 URL 或 Blob URL）
      downloadLink.href = fileDownUrl;
      // 设置下载文件名（仅对同源 URL 或 Blob URL 生效，跨域需后端配合）
      downloadLink.download = finalFilename;
      // 隐藏链接（不影响页面布局）
      downloadLink.style.display = 'none';

      // 4. 处理跨域下载的兼容性（若 fileDownUrl 是跨域链接，a 标签 download 可能失效）
      const isCrossOrigin = new URL(fileDownUrl).origin !== window.location.origin;
      if (isCrossOrigin) {
        console.warn('注意：当前为跨域下载链接，a标签download属性可能失效，需后端配置CORS或提供下载接口');
        // 跨域场景备选方案：通过iframe触发下载（需后端支持）
        const iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        iframe.src = fileDownUrl;
        document.body.appendChild(iframe);
        
        // 监听iframe加载状态，判断下载是否触发
        iframe.onload = () => {
          setTimeout(() => {
            document.body.removeChild(iframe);
            resolve('跨域下载已触发（请确认浏览器下载弹窗）');
          }, 300);
        };
        iframe.onerror = (error) => {
          document.body.removeChild(iframe);
          const err = new Error(`跨域下载失败：${error.message}`);
          console.error(err);
          reject(err);
        };
        return;
      }

      // 5. 同源/Blob URL 场景：直接通过a标签触发下载
      document.body.appendChild(downloadLink);
      // 模拟点击触发下载（部分浏览器需手动触发）
      downloadLink.click();

      // 6. 清理DOM和资源，避免内存泄漏
      setTimeout(() => {
        document.body.removeChild(downloadLink);
        // 若为 Blob URL，需手动释放（避免占用内存）
        if (fileDownUrl.startsWith('blob:')) {
          URL.revokeObjectURL(fileDownUrl);
        }
        resolve('模型下载已触发');
      }, 100);

    } catch (error) {
      // 捕获意外错误（如DOM操作失败、URL解析异常等）
      const err = new Error(`下载处理失败：${error.message}`);
      console.error(err);
      reject(err);
    }
  });
}

// ------------------------------
// 全屏功能
// ------------------------------
function toggleFullscreen() {
  const targetContainer = containerRef;
  const canvasDom = targetContainer.children[0]; // 获取canvas元素
  const width = canvasDom.style.width;
  const height = canvasDom.style.height;
  if (!targetContainer) {
    console.error("无法切换全屏：容器未初始化");
    return false;
  }

  if (!document.fullscreenElement) {
    if (targetContainer.requestFullscreen) {
      targetContainer.requestFullscreen().catch(err => console.error("进入全屏失败", err));
    } else if (targetContainer.webkitRequestFullscreen) {
      targetContainer.webkitRequestFullscreen();
    } else if (targetContainer.mozRequestFullScreen) {
      targetContainer.mozRequestFullScreen();
    } else if (targetContainer.msRequestFullscreen) {
      targetContainer.msRequestFullscreen();
    }
    canvasDom.style.width = "100%";
    canvasDom.style.height = '100%';
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    }
    canvasDom.style.width = width + "px";
    canvasDom.style.height = height + "px";
  }

  return !!document.fullscreenElement;
}

function toggleModelSelection() {
  if (!bodyModel) return isModelSelected;

  isModelSelected = !isModelSelected;
  bodyModel.traverse((obj) => {
    if (obj.isMesh) {
      if (isModelSelected) {
        obj.userData.originalMaterial = obj.userData.originalMaterial || obj.material;
        obj.material = new THREE.MeshBasicMaterial({
          color: 0xffff00,
          wireframe: true,
          transparent: true,
          opacity: 0.8
        });
      } else {
        if (obj.userData.originalMaterial) {
          obj.material = obj.userData.originalMaterial;
        }
      }
    }
  });

  return isModelSelected;
}

function getModelSelectionState() {
  return isModelSelected;
}

// ------------------------------
// 附加模型切换功能
// ------------------------------
// function handleChangeGlb(targetUrl, action) {
//   return new Promise((resolve, reject) => {
//     if (!currentGlbList.length || !loader) {
//       reject(new Error("附加模型配置未初始化"));
//       return;
//     }

//     const targetGlbConfig = currentGlbList.find(item => item.url === targetUrl);
//     if (!targetGlbConfig) {
//       reject(new Error(`未找到模型配置：${targetUrl}`));
//       return;
//     }

//     const urlIndex = addGltfModel.findIndex(item => item.url === targetUrl);
//     const modelTypeIndex = addGltfModel.findIndex(item => item.model === targetGlbConfig.model);

//     // 移除旧模型
//     if (targetGlbConfig.model === "glassesModel" && glassesModel) {
//       scene.remove(glassesModel);
//     } else if (targetGlbConfig.model === "faceModel" && faceModel) {
//       scene.remove(faceModel);
//     }

//     if (action === "add") {
//       loader.load(
//         targetUrl,
//         (gltf) => {
//           const newModel = gltf.scene;
//           if (targetGlbConfig.model === "glassesModel") {
//             glassesModel = newModel;
//           } else if (targetGlbConfig.model === "faceModel") {
//             faceModel = newModel;
//           }

//           // 设置位置和旋转
//           newModel.position.set(
//             targetGlbConfig.position?.x || 0,
//             targetGlbConfig.position?.y || 0,
//             targetGlbConfig.position?.z || 0
//           );
//           const rotateX = targetGlbConfig.rotation?.x ? (targetGlbConfig.rotation.x / 180) * Math.PI : 0;
//           const rotateY = targetGlbConfig.rotation?.y ? (targetGlbConfig.rotation.y / 180) * Math.PI : 0;
//           const rotateZ = targetGlbConfig.rotation?.z ? (targetGlbConfig.rotation.z / 180) * Math.PI : 0;
//           newModel.rotation.set(rotateX, rotateY, rotateZ);

//           // 更新模型列表
//           if (urlIndex === -1 && modelTypeIndex === -1) {
//             addGltfModel.push({ url: targetUrl, model: targetGlbConfig.model, group: newModel });
//           } else if (modelTypeIndex !== -1) {
//             addGltfModel[modelTypeIndex] = { url: targetUrl, model: targetGlbConfig.model, group: newModel };
//           }

//           scene.add(newModel);
//           resolve();
//         },
//         undefined,
//         (error) => reject(error)
//       );
//     } else if (action === "remove" && urlIndex !== -1) {
//       addGltfModel.splice(urlIndex, 1);
//       resolve();
//     } else {
//       reject(new Error(`无效操作：${action}`));
//     }
//   });
// }

// ------------------------------
// 额外扩展功能：重置视图
// ------------------------------
// function resetView() {
//   if (!bodyModel) return;
//   fitModelToContainer(bodyModel); // 重新适配模型显示
// }

// ------------------------------
// 资源清理
// ------------------------------
function dispose() {
  // 停止渲染循环
  const originalAnimate = animate;
  let animateId;
  animate = () => { animateId = requestAnimationFrame(animate); };
  cancelAnimationFrame(animateId);
  animate = originalAnimate;
  // 移除事件监听
  window.removeEventListener('resize', handleResize);

  // 释放资源
  if (renderer) renderer.dispose();
  if (scene) {
    scene.traverse((obj) => {
      if (obj.geometry) obj.geometry.dispose();
      if (obj.material) {
        Array.isArray(obj.material) 
          ? obj.material.forEach(mat => mat.dispose())
          : obj.material.dispose();
      }
    });
  }

  // 重置变量
  scene = null;
  renderer = null;
  camera = null;
  controls = null;
  bodyModel = null;
  glassesModel = null;
  faceModel = null;
  containerRef = null;
  // 其他变量重置...
}

// ------------------------------
// 对外暴露的方法
// ------------------------------
export const show3D = {
  init,
  animate,
  dispose,
  handleResize, // 暴露尺寸调整方法，供外部调用
  
  // 核心功能
  downloadModel, // 下载
  toggleFullscreen, // 全屏
  toggleModelSelection, // 切换模型选择
  getModelSelectionState, // 获取模型选择状态
  // handleChangeGlb, // 切换附加模型
  // resetView // 重置视图到完整显示模型
};
